<?php

namespace App\Modules\Popularize\Platform;


use App\Http\Model\Device;
use App\Http\Model\User;
use App\Http\Model\UserRegisterLog;
use Illuminate\Support\Facades\Redis;

class PlatformXiaomi implements PlatformInterface
{

    protected $callback;
    protected $platform;
    protected $device;
    protected $userId;

    //小米参数配置
    const APP_ID = 968693;
    const CUSTOMER_ID = 254052;

    //事件类型配置
    const ACTIVITE_EVENT = "APP_ACTIVE"; //激活
    const REGISTER_EVENT = 'APP_REGISTER'; //注册
    const PAY_EVENT = 'APP_PAY'; //付费


    //小米平台每个跟踪记录都有不同的密钥
    const SECRET_KEY = [
        self::ACTIVITE_EVENT => [
            'encryptKey' => 'aXoqAaYZkvYCvZop',
            'signKey' => 'QloMzeKaQHwsrDMu',
        ],
        self::REGISTER_EVENT => [
            'encryptKey' => 'IpxIBTYeQkxBaTTN',
            'signKey' => 'CPltOwAPVpwyXUAF',
        ],
        self::PAY_EVENT => [
            'encryptKey' => 'fucixSzQIKpiEsPv',
            'signKey' => 'SDxkGiTPjsPDTjXb',
        ],
    ];
    
    protected $redisPay = 'ADVERTISEMENT:MI:PAY:%s'; //汇报记录，防止多次汇报

    public function __construct($callback, $platform, $device, $userId = 0)
    {
        $this->callback = $callback;
        $this->platform = $platform;
        $this->device = $device;
        $this->userId = $userId;
    }

    /**
     * 激活
     * @return bool|null
     */
    public function active(): ?bool
    {
        $params = json_decode(json_encode($this->device), true);
        $params['platform'] = empty($params['platform']) ? $this->platform : $params['platform'];

        if(empty($this->device->guid)){
            write_log('Platform', 'platform_xiaomi', ["激活时guid为空",$params]);
            return false;
        }

        try {
            //查询是否存在设备信息，如果存在就说明设备已经激活
            $deviceModel = new Device();
            $deviceInfo = $deviceModel->getByGuid($this->device->guid);
            if (!empty($deviceInfo)) {
                write_log('Platform', 'platform_xiaomi', ["设备已存在", $params]);
                return false;
            }

            $deviceModel->save($params);

            //获取用户注册并修改渠道
            $model = new UserRegisterLog();
            $userRegisterLog = $model->findRecordByGuid($this->device->guid, ['user_id']);
            if ($userRegisterLog && $this->platform != '' && is_numeric($userRegisterLog['platform']) && $userRegisterLog['platform'] == $userRegisterLog['channel_id']) {
                $model->updatePlatform($userRegisterLog['user_id'], $this->platform);
            }

            write_log('Platform', 'platform_xiaomi', ["保存设备信息成功", $params]);

            //发送数据
            $imei = $params['imei'] ?? "";
            $oaid = $params['oaid'] ?? "";
            $this->_report(self::ACTIVITE_EVENT, $imei, $oaid);

            return true;

        } catch (\Exception $e) {
            write_log('Platform', 'platform_xiaomi', ["保存设备信息失败", $params, $e->getMessage()]);
            return false;
        }
    }

    /**
     * 注册
     * @return bool|null
     */
    public function regist(): ?bool
    {
        $this->_report(self::REGISTER_EVENT, $this->device->imei, $this->device->oaid);
        return true;
    }

    /**
     * 付费
     * @param $amount
     * @return bool|null
     */
    public function pay($amount = 0): ?bool
    {
        //规定时间内注册且付费才上报
        $user = (new User())->get_user($this->userId, true);
        if (time() - $user['create_timestamp'] > 86400) {
            return true;
        }

        //只上报一次
        $key = sprintf($this->redisPay, $this->userId);
        $ret = Redis::set($key, 1, 'nx', 'ex', 86400);
        if (!$ret) {
            return true;
        }

        $userRegisterLog = (new UserRegisterLog())->getUserRegisterLog($this->userId);
        $deviceinfo = (new Device())->getByGuid($userRegisterLog->guid);
        //发送数据
        $imei = $deviceinfo[0]['imei'] ?? "";
        $oaid = $deviceinfo[0]['oaid'] ?? "";

        $this->_report(self::PAY_EVENT, $imei, $oaid);
        return true;
    }

    /**
     * 推送请求
     * @param $type string 回传类型
     * @param $imei string
     * @param $oaid string
     * @return bool
     */
    private function _report($type, $imei, $oaid)
    {
        if (empty($imei) && empty($oaid)) {
            write_log('miCallbackLogs', 'platform_xiaomi _report 数据为空', ['type' => $type, 'userId' => $this->userId ?? ""]);
            return false;
        }

        if (!isset(self::SECRET_KEY[$type])) {
            return false;
        }

        $miDataStr = '';
        $idfaArr = ['00000000-0000-0000-0000-000000000000', '00000000000000000000000000000000', ''];
        if ($imei && !in_array($imei, $idfaArr)) {
            $miDataStr = 'imei=' . urlencode(md5($imei));
        }

        if ($oaid && !in_array($oaid, $idfaArr)) {
            $miDataStr = $miDataStr ? $miDataStr . '&' : '';
            $miDataStr .= 'oaid=' . urlencode($oaid);
        }

        if (!$miDataStr) {
            return false;
        }

        $miDataStr .= '&conv_time=' . urlencode(time() * 1000);

        $sign = md5(self::SECRET_KEY[$type]['signKey'] . '&' . urlencode($miDataStr));
        $beforData = $this->dataXor($miDataStr . '&sign=' . urlencode($sign), self::SECRET_KEY[$type]['encryptKey']);

        if (!$beforData) {
            return false;
        }
        $miData = base64_encode($beforData);
        $datalist = [
            'appId' => urlencode(self::APP_ID),
            'info' => urlencode($miData),
            'conv_type' => urlencode($type),
            'customer_id' => urlencode(self::CUSTOMER_ID),
        ];

        $url = 'http://trail.e.mi.com/global/log?' . http_build_query($datalist);

        $result = curl_request($url, [], 'json', 'GET');
        write_log('miCallbackLogs', 'platform_xiaomi Request', ['type' => $type, 'oaid' => $oaid, 'imei' => $imei, 'datalist' => $datalist]);
        write_log('miCallbackLogs', 'platform_xiaomi Response', ['type' => $type, 'oaid' => $oaid, 'imei' => $imei, 'datalist' => $datalist, 'result' => $result]);

        return true;
    }

    /**
     * 异或加密
     * @param string $data
     * @param string $key
     */
    private function dataXor(string $data, string $key)
    {
        if (empty($data) || empty($key)) {
            return false;
        }
        $dataLen = strlen($data);
        $keyLen = strlen($key);
        $newdata = '';
        for ($i = 0; $i < $dataLen; $i++) {
            $newdata .= $data[$i] ^ $key[$i % $keyLen];
        }
        return $newdata;
    }

}
